Embed ZK Component in Foreign Framework
Employment/Purpose
Here we describe how to embed ZK component(s) as a native element of a foreign framework. For example, how ZK components can be embedded as a native JSF component. It allows application developers to use the native element without knowing the existence of ZK.
For the sake of description, we call it the embedded component.
Note: If it is OK for your developers to work on ZUL directly, it is more convenient and powerful to use the inclusion (such as <jsp:include>) or ZK JSP Tags, and you don't have to wrap them into a native element.
Prerequisite
DOCTYPE
To use ZK components correctly, the pages generated by the foreign framework (JSP, JSF...) must generate the doc type as follows.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Browser Cache
Though optional, it is suggested to disable the browser to cache the result page. It can be done as follows.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
Embed a component directly
The simplest way to embed is to invoke Renders.render(ServletContext, HttpServletRequest, HttpServletResponse, Component, String, Writer) when it is time to output the content of the native element.
For example, if you are implementing a JSP tag, then you can invoke the render method in doTag()
as follows.
1 public void doTag() throws JspException, IOException {
2 //prepare variables
3 final JspContext jspctx = getJspContext();
4 final PageContext pgctx = Jsps.getPageContext(jspctx);
5 final ServletContext svlctx = pgctx.getServletContext();
6 final HttpServletRequest request = (HttpServletRequest)pgctx.getRequest();
7 final HttpServletResponse response = (HttpServletResponse)pgctx.getResponse();
8
9 //create components
10 Listbox listbox = new Listbox();
11 listbox.appendChild(new Listitem("Item 1"));
12 listbox.appendChild(new Listitem("Item 2"));
13
14 //render the result
15 final StringWriter out = new StringWriter();
16 Renders.render(svlctx, request, response, listbox, null, out);
17 getJspBody().invoke(out);
18 }
Embed by implementing a richlet
If you want to have more control, such as applying a composer provided by users or creating components from a ZUL page, you could implement a richlet (Richlet) and then invoke Renders.render(ServletContext, HttpServletRequest, HttpServletResponse, Richlet, String, Writer) instead.
1 Renders.render(svlctx, request, response,
2 new GenericRichlet() {
3 public void service(Page page) throws Exception {
4 //execution is ready
5 //... do whatever you want
6 Window main = new Window();
7 main.setPage(page); //associate to the page
8 Executions.createComponents("/WEB-INF/template/foo.zul", main, null);
9 composer.doAfterCompose(main); //assume user assigned a composer
10 }
11 }, null, out);
where we use GenericRichlet to simplify the implementation of a richlet.
Example
Embed as a native JSF component
ZK Component as a native JSF component can be easily achieved by wrapping it as a custom JSF component [1] and rendering it in Render Response Phase of JSF lifecycle by invoking Renders.render(ServletContext, HttpServletRequest, HttpServletResponse, Richlet, String, Writer)
1 @FacesComponent(value = "window")
2 public class WindowTag extends UIComponentBase {
3 private static final Log log = Log.lookup(WindowTag.class);
4 private Window window;
5
6 public void encodeBegin(FacesContext context) throws IOException {
7 ServletContext svlctx = (ServletContext)context.getExternalContext().getContext();
8 HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
9 HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
10 ResponseWriter responseWriter = context.getResponseWriter();
11
12 try {
13 Renders.render(svlctx, request,response,
14 new GenericRichlet() {
15 public void service(Page page) throws Exception {
16 window = new Window();
17 window.setPage(page);
18 applyProperties();
19 doAfterCompose();
20 }
21 }, null, responseWriter);
22 } catch (ServletException e) {
23 throw new IOException(e.getMessage());
24 }
25 }
26
27 /** apply ZK component properties as retrieved from JSF custom component tag */
28 private void applyProperties() {
29 Map<String, Object> attrs = getAttributes();
30 Set<String> attrNames = attrs.keySet();
31
32 for (Iterator iterator = attrNames.iterator(); iterator.hasNext();) {
33 String attrName = (String) iterator.next();
34 if(!"apply".equals(attrName)) {
35 try {
36 Property.assign(window, attrName, attrs.get(attrName).toString());
37 } catch(PropertyNotFoundException pnfe) {
38 log.debug(pnfe.getMessage());
39 }
40 }
41 }
42 }
43 /** apply composer by calling doAfterCompose after ZK component is composed */
44 private void doAfterCompose() throws Exception {
45 Object o = getAttributes().get("apply");
46 if(o instanceof String) {
47 o = Classes.newInstanceByThread(o.toString());
48 }
49 if(o instanceof Composer) {
50 ((Composer)o).doAfterCompose(window);
51 }
52 }
53
54 ....
55 }
Version History
Version | Date | Content |
---|---|---|
5.0.5 | September 2010 | Renders was introduced to simplify the making of a native element for a foreign framework. |